package gui;

import static gui.GUIUtils.checkIfEmpy;
import static gui.GUIUtils.getTextFromPasswordField;
import static gui.GUIUtils.reverse;
import static gui.utilities.Verifiers.verifyEmail;
import static gui.utilities.Verifiers.verifyUserName;
import gui.utilities.FileDrop;
import gui.utilities.ImageFilter;
import gui.utilities.ImagePreview;

import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Calendar;

import javax.imageio.ImageIO;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

import algorithms.SHA1;
import core.exceptions.DBAccessException;
import core.objects.Country;
import core.objects.User;
import core.objects.enums.GenderEnum;
import db.DBAccessEngine;
import db.IDBAccess;
/**
 *
 * @author abadi
 */
public class SignUpForm extends JFrame {
    
    private static final long serialVersionUID = 1L;
    private static final String INTIAL_IMAGE_PATH_TEXT_FIELD_TEXT = "Pick an image or Drag&Drop here";

    
    
    /**
     * Creates new form SignUpForm
     */
    public SignUpForm() {
        initComponents();
        setLocationRelativeTo(null);
        initAuxComponents();
        
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this
     * code. The content of this method is always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

    	try {
    		setIconImage(ImageIO.read(JFrameConstructDB.class.getResourceAsStream("/resources/icon.png")));
    	} catch (Exception e) {
    		//do nothing
    	}
    	
        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        jTextFieldUserName = new javax.swing.JTextField();
        jLabel10 = new javax.swing.JLabel();
        jTextFieldEmail = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        jTextFieldFirstName = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        jTextFieldLastName = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jPasswordField1 = new javax.swing.JPasswordField();
        jLabel6 = new javax.swing.JLabel();
        jPasswordField2 = new javax.swing.JPasswordField();
        jLabel11 = new javax.swing.JLabel();
        jPanel3 = new javax.swing.JPanel();
        jComboDay = new javax.swing.JComboBox();
        jComboMonth = new javax.swing.JComboBox();
        jComboYear = new javax.swing.JComboBox();
        jLabel7 = new javax.swing.JLabel();
        jComboBoxGender = new javax.swing.JComboBox();
        jLabel8 = new javax.swing.JLabel();
        Country countries[];
        try{
            countries = GUIUtils.genCountriesArray();
        }catch(DBAccessException ex){
            GUIUtils.showMessageError(ex, this);
            countries = null;
        }
        jComboBoxCountry = new javax.swing.JComboBox(countries);
        jLabel9 = new javax.swing.JLabel();
        jTextFieldImagePath = new javax.swing.JTextField();
        jButtonSignUp = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Loan-a-Book");
        setBackground(new java.awt.Color(51, 153, 255));
        setLocationByPlatform(true);
        setResizable(false);

        jPanel1.setBackground(new java.awt.Color(51, 153, 255));
        jPanel1.setMaximumSize(new java.awt.Dimension(348, 343));
        jPanel1.setMinimumSize(new java.awt.Dimension(348, 343));

        jLabel1.setBackground(new java.awt.Color(51, 153, 255));
        jLabel1.setFont(new java.awt.Font("Trebuchet MS", 1, 24)); // NOI18N
        jLabel1.setForeground(new java.awt.Color(153, 255, 153));
        jLabel1.setText("Sign Up ");

        jPanel2.setBackground(new java.awt.Color(51, 153, 255));
        jPanel2.setOpaque(false);
        jPanel2.setLayout(new java.awt.GridLayout(10, 2));

        jLabel2.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel2.setForeground(new java.awt.Color(153, 255, 153));
        jLabel2.setText("User Name");
        jPanel2.add(jLabel2);

        jTextFieldUserName.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                jTextFieldUserNameFocusLost(evt);
            }
        });
        jPanel2.add(jTextFieldUserName);

        jLabel10.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel10.setForeground(new java.awt.Color(153, 255, 153));
        jLabel10.setText("Email");
        jPanel2.add(jLabel10);

        jTextFieldEmail.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                jTextFieldEmailFocusLost(evt);
            }
        });
        jPanel2.add(jTextFieldEmail);

        jLabel3.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel3.setForeground(new java.awt.Color(153, 255, 153));
        jLabel3.setText("First Name");
        jPanel2.add(jLabel3);
        jPanel2.add(jTextFieldFirstName);

        jLabel4.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel4.setForeground(new java.awt.Color(153, 255, 153));
        jLabel4.setText("Last Name");
        jPanel2.add(jLabel4);
        jPanel2.add(jTextFieldLastName);

        jLabel5.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel5.setForeground(new java.awt.Color(153, 255, 153));
        jLabel5.setText("Password");
        jPanel2.add(jLabel5);
        jPanel2.add(jPasswordField1);

        jLabel6.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel6.setForeground(new java.awt.Color(153, 255, 153));
        jLabel6.setText("Re-enter Password");
        jPanel2.add(jLabel6);

        jPasswordField2.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                jPasswordField2FocusLost(evt);
            }
        });
        jPanel2.add(jPasswordField2);

        jLabel11.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel11.setForeground(new java.awt.Color(153, 255, 153));
        jLabel11.setText("Birthday");
        jPanel2.add(jLabel11);

        jPanel3.setOpaque(false);
        jPanel3.setLayout(new javax.swing.BoxLayout(jPanel3, javax.swing.BoxLayout.X_AXIS));

        jComboDay.setModel(new DefaultComboBoxModel(getIntList(1, 31))
        );
        jPanel3.add(jComboDay);

        jComboMonth.setModel(new DefaultComboBoxModel(getIntList(1, 12)));
        jPanel3.add(jComboMonth);

        jComboYear.setModel(new DefaultComboBoxModel(reverse(getIntList(1920, 2014))));
        jPanel3.add(jComboYear);

        jPanel2.add(jPanel3);

        jLabel7.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel7.setForeground(new java.awt.Color(153, 255, 153));
        jLabel7.setText("Gender");
        jPanel2.add(jLabel7);

        jComboBoxGender.setModel(new javax.swing.DefaultComboBoxModel(GenderEnum.values()));
        jPanel2.add(jComboBoxGender);

        jLabel8.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel8.setForeground(new java.awt.Color(153, 255, 153));
        jLabel8.setText("Country");
        jPanel2.add(jLabel8);

        jPanel2.add(jComboBoxCountry);

        jLabel9.setFont(new java.awt.Font("Trebuchet MS", 1, 13)); // NOI18N
        jLabel9.setForeground(new java.awt.Color(153, 255, 153));
        jLabel9.setText("Profile Picture");
        jPanel2.add(jLabel9);

        jTextFieldImagePath.setForeground(new java.awt.Color(102, 102, 102));
        jTextFieldImagePath.setText(INTIAL_IMAGE_PATH_TEXT_FIELD_TEXT);
        jTextFieldImagePath.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextFieldImagePathActionPerformed(evt);
            }
        });
        jTextFieldImagePath.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                jTextFieldImagePathFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                jTextFieldImagePathFocusLost(evt);
            }
        });
        jPanel2.add(jTextFieldImagePath);

        jButtonSignUp.setText("Sign Up");
        jButtonSignUp.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonSignUpActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGap(170, 170, 170)
                .addComponent(jLabel1)
                .addGap(0, 180, Short.MAX_VALUE))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(jButtonSignUp, javax.swing.GroupLayout.PREFERRED_SIZE, 233, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jLabel1)
                .addGap(11, 11, 11)
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 282, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButtonSignUp, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jPasswordField2FocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jPasswordField2FocusLost
        if (!getTextFromPasswordField(jPasswordField1).equals("")) {
            verifyPassword();
        }
    }//GEN-LAST:event_jPasswordField2FocusLost
    
    private void jTextFieldUserNameFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jTextFieldUserNameFocusLost
        if (!jTextFieldUserName.getText().equals("")) {
            verifyUserName(jTextFieldUserName.getText(),this);
        }
    }//GEN-LAST:event_jTextFieldUserNameFocusLost
    
    @SuppressWarnings("unchecked")
	private void jButtonSignUpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonSignUpActionPerformed
        if (!verifyUserName(jTextFieldUserName.getText(),this) || !verifyEmail(jTextFieldEmail.getText(),this) || !verifyPassword() || !verifyImagePath(jTextFieldImagePath)) {
            return;
        }
        
        jButtonSignUp.setVisible(false);
        
        byte[] imageArr =  null;
        if (!jTextFieldImagePath.getText().equals("")){
            try {
                imageArr = Files.readAllBytes(new File(jTextFieldImagePath.getText()).toPath());
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(this, "Image Format is not supported!", "Error", JOptionPane.ERROR_MESSAGE);
                jButtonSignUp.setVisible(true);
                return;
            }
        }
        
        String hashedPass = SHA1.toSHA1(getTextFromPasswordField(jPasswordField1));
        String userName = jTextFieldUserName.getText();
        String firstName = checkIfEmpy(jTextFieldFirstName.getText());
        String lastName = checkIfEmpy(jTextFieldLastName.getText());
        String genderStr = jComboBoxGender.getSelectedItem().toString();
        GenderEnum gender = genderStr.equals("") ? null : GenderEnum.valueOfString(genderStr);
        
        int countryId = ((Country) jComboBoxCountry.getSelectedItem()).getID();
        int cityId = -1;//((City) jComboBoxCity.getSelectedItem()).getID();

        Calendar cal = Calendar.getInstance();
        int year = Integer.parseInt(jComboYear.getSelectedItem().toString());
        int month = Integer.parseInt(jComboMonth.getSelectedItem().toString());
        int day = Integer.parseInt(jComboDay.getSelectedItem().toString());
        cal.set(year, month - 1, day, 0, 0, 0);
        String email = jTextFieldEmail.getText();
        
        User user = new User(0, userName, firstName, lastName, hashedPass, gender, cal, cityId, countryId, imageArr, email);
        try {
            ((IDBAccess<User>) DBAccessEngine.User()).insert(user);
        } catch (DBAccessException ex) {
            GUIUtils.showMessageError(ex, this);
            jButtonSignUp.setVisible(true);
            return;
        }
        dispose();
    }//GEN-LAST:event_jButtonSignUpActionPerformed
    private boolean popFileChooser = true;
    private void jTextFieldImagePathFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jTextFieldImagePathFocusGained
        if (popFileChooser) {
            JFileChooser fileChooser = new JFileChooser();
             fileChooser.setFileFilter(new ImageFilter());
             fileChooser.setAcceptAllFileFilterUsed(false);

	    //Add the preview pane.
            fileChooser.setAccessory(new ImagePreview(fileChooser));
            
            if (!jTextFieldImagePath.getText().equals(INTIAL_IMAGE_PATH_TEXT_FIELD_TEXT)) {
                fileChooser.setCurrentDirectory(new File(jTextFieldImagePath.getText()));
            }
            int retVal = fileChooser.showOpenDialog(this);
            popFileChooser = false;
            if (retVal == JFileChooser.APPROVE_OPTION) {
                jTextFieldImagePath.setText(fileChooser.getSelectedFile().getAbsolutePath());
                jButtonSignUp.requestFocus();
            } else {
                jTextFieldImagePath.setSelectionStart(0);
                jTextFieldImagePath.setSelectionEnd(jTextFieldImagePath.getText().length());
            }
        }
    }//GEN-LAST:event_jTextFieldImagePathFocusGained
    
    private void jTextFieldImagePathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextFieldImagePathActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_jTextFieldImagePathActionPerformed
    
    private void jTextFieldImagePathFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jTextFieldImagePathFocusLost
        popFileChooser = true;
        GUIUtils.handleJTextFieldFocusLost(jTextFieldImagePath, INTIAL_IMAGE_PATH_TEXT_FIELD_TEXT);
    }//GEN-LAST:event_jTextFieldImagePathFocusLost

    private void jTextFieldEmailFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jTextFieldEmailFocusLost
        if (jTextFieldEmail.getText().equals("")) return;
        verifyEmail(jTextFieldEmail.getText(), this);
    }//GEN-LAST:event_jTextFieldEmailFocusLost
    
    public static void runGUI(final JFrame parentFrame) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(SignUpForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(SignUpForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(SignUpForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(SignUpForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
			public void run() {
                SignUpForm suf = new SignUpForm();
                suf.setVisible(true);
                suf.parentFrame = parentFrame;
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonSignUp;
    private javax.swing.JComboBox jComboBoxCountry;
    private javax.swing.JComboBox jComboBoxGender;
    private javax.swing.JComboBox jComboDay;
    private javax.swing.JComboBox jComboMonth;
    private javax.swing.JComboBox jComboYear;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPasswordField jPasswordField1;
    private javax.swing.JPasswordField jPasswordField2;
    private javax.swing.JTextField jTextFieldEmail;
    private javax.swing.JTextField jTextFieldFirstName;
    private javax.swing.JTextField jTextFieldImagePath;
    private javax.swing.JTextField jTextFieldLastName;
    private javax.swing.JTextField jTextFieldUserName;
    // End of variables declaration//GEN-END:variables
    private JFrame parentFrame;
    
    private void initAuxComponents() {
        //Add Drag&Drop Capabilities
        new FileDrop(this, new FileDrop.Listener() {
            @Override
			public void filesDropped(java.io.File[] files) {
                jTextFieldImagePath.setText(files[0].getAbsolutePath());
            } // end filesDropped
        }); // end FileDrop.Listener
        
        jButtonSignUp.setMinimumSize(jComboBoxCountry.getSize());
        jButtonSignUp.setPreferredSize(jComboBoxCountry.getSize());
    }
    
     private boolean verifyImagePath(JTextField pathJtext) {
        GUIUtils.handleJTextFieldFocusGained(pathJtext, INTIAL_IMAGE_PATH_TEXT_FIELD_TEXT);
        if (pathJtext.getText().equals("")) {
            return true;
        }
        try {
            Image img = ImageIO.read(new File(pathJtext.getText()));
            if (img == null) {
                JOptionPane.showMessageDialog(this, "The file provided is not a valid picture!", "Error", JOptionPane.ERROR_MESSAGE);
                return false;
            }
        } catch (IOException ex) {
            return false;
        }
        return true;
    }

    private boolean verifyPassword() {
        String str1 = getTextFromPasswordField(jPasswordField1);
        String str2 = getTextFromPasswordField(jPasswordField2);
        if (str1.length() < 6) {
            JOptionPane.showMessageDialog(this, "Password must be at least 6 characters", "Error", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        if (!str1.equals(str2)) {
            JOptionPane.showMessageDialog(this, "Password fields do not match!", "Error", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        return true;
    }
    
    private String[] getIntList(int start, int end) {
        String[] arr = new String[end - start + 1];
        for (int i = 0; i <= end - start; i++) {
            arr[i] = "" + (start + i);
        }
        return arr;
    }
    
    @Override
    public void dispose() {
        super.dispose();
        parentFrame.setVisible(true);
    }
}
